package com.sourcetrip.raw.adt;


import com.sourcetrip.raw.adt.abs.MyAbstractLinkedList;

/**
 * @author: ZhouBert
 * @date: 2020/11/18
 * @description: 关于 AbstractList（抽象类，不一定就是jdk 源码中的）提取共性的方法：
 * add(int index, E element) -> 实际就是调用 add(size)
 */
public class MySingleLinkedList2<E> extends MyAbstractLinkedList<E> {
	/**
	 * 哨兵节点
	 * 而 cur 尾部节点就不安排了，因为用处不大
	 */
	private MySingleNode<E> guard = new MySingleNode<E>(null, null);


	/**
	 * 关键方法
	 * 处理好了以后，其他方法可以套用！
	 *
	 * @param index
	 * @return
	 */
	@Override
	public E get(int index) {
		checkIndex4get(index);
		return node(index).getElement();
	}

	/**
	 * 思路:
	 * 1.获取 index -1 的 Node,同时获得 index 的 Node;
	 * 2.改变 index -1 的 next,将 next 节点的内存值赋值给新 new 出来的 Node
	 *
	 * @param index
	 * @param element
	 */
	@Override
	public void add(int index, E element) {
		checkIndex4add(index);
		//拿到 pre 节点
		MySingleNode<E> pre = node(index - 1);
		pre.setNext(new MySingleNode(element, pre.getNext()));
		size++;
	}


	/**
	 * 设置索引当前节点，并返回 oldValue
	 *
	 * @param index
	 * @param element
	 * @return
	 */
	@Override
	public E set(int index, E element) {
		checkIndex4get(index);
		//拿到 cur 节点
		MySingleNode<E> cur = node(index);
		E oldValue = cur.getElement();
		cur.setElement(element);
		return oldValue;
	}

	@Override
	public E remove(int index) {
		checkIndex4get(index);
		//拿到 pre 节点
		MySingleNode<E> pre = node(index - 1);
		MySingleNode<E> cur = pre.getNext();
		E oldValue = cur.getElement();
		pre.setNext(cur.getNext());
		cur.setNext(null);
		size--;
		return oldValue;
	}

	/**
	 * 判断相同这点上：
	 * null 和 !null 不同
	 *
	 * @param element
	 * @return
	 */
	@Override
	public int indexOf(E element) {
		MySingleNode<E> node = this.guard;
		if (element == null) {
			for (int i = 0; i < size; i++) {
				node = node.getNext();
				if (node.getElement() == null) {
					return i;
				}
			}
		} else {
			for (int i = 0; i < size; i++) {
				node = node.getNext();
				if (element.equals(node.getElement())) {
					return i;
				}
			}
		}
		return -1;
	}

	@Override
	public void clear() {
		guard.setNext(null);
		size = 0;
	}

	@Override
	public String toString() {
		MySingleNode<E> node = this.guard.getNext();
		StringBuilder sb = new StringBuilder();
		sb.append("[");

		while (node != null) {
			sb.append(node.getElement());
			node = node.getNext();
			if (node != null) {
				sb.append(", ");
			}
		}
		sb.append("]");
		return sb.toString();
	}

	//region	private methods

	/**
	 * 根据索引值获取对应的节点
	 *
	 * @param index "索引"
	 * @return
	 */
	private MySingleNode<E> node(int index) {
		MySingleNode<E> node = this.guard;
		for (int i = 0; i <= index; i++) {
			node = node.getNext();
		}
		return node;
	}


	//endregion
}
